/******************************************************
* Team WB
* Brett Cate, William Kim
* 
* Register16 ADT Source
*******************************************************/

#include "register16.h"

/*
Creates a new Register object and returns a pointer to it.

return value: A pointer to the newly created Register.
*/
RegisterPtr register_new() {
	RegisterPtr register_ptr = (RegisterPtr) malloc(sizeof(ushort));

	// Generates a random number between 0 and MAX_USHORT_VALUE and assigns it to *register_ptr
	*register_ptr = rand() / (RAND_MAX/MAX_USHORT_VAL + 1); 
	return register_ptr;
}

/*
Returns the unsigned char contained in the low order byte of the given register.

parameter (the_registerPtr): pointer to the register whose low order byte is returned.
parameter (*the_error): Pointer to the int value for the error code of this function.

return value: A uchar containing the low order byte of the given register.
*/
uchar register_getLowByte(RegisterPtr the_registerPtr, int* the_error) {
	uchar low_byte;
	if (the_registerPtr == NULL) {
		*the_error = NULL_POINTER_ERROR;
		return 0;
	}
	low_byte = (uchar) *the_registerPtr;
	*the_error = NO_ERROR;
	return low_byte;
}

/*
Returns the high order byte of the given register.

parameter (the_registerPtr): pointer to the register whose high order byte is returned.
parameter (*the_error): Pointer to the int value for the error code of this function.

return value: A uchar containing the high order byte of the given register.
*/
uchar register_getHIByte(RegisterPtr the_registerPtr, int* the_error) {
	uchar high_byte;
	if(the_registerPtr == NULL) {
		*the_error = NULL_POINTER_ERROR;
		return 0;
	}
	high_byte = *the_registerPtr >> 8;
	*the_error = NO_ERROR;
	return high_byte;
}

/*
Puts the given byte in the low order byte of the given register, and returns the error code.

parameter (the_registerPtr): Pointer to the register whose low order byte is changed.
parameter (the_byte): The byte to be placed in the given register.

return value: The error code for this function as an int.
*/
int register_putLowByte(RegisterPtr the_registerPtr, uchar the_byte) {
	if (the_registerPtr == NULL) {
		return NULL_POINTER_ERROR;
	}
	*the_registerPtr = *the_registerPtr & 0xFF00;
	*the_registerPtr = *the_registerPtr | the_byte;
	return NO_ERROR;
}

/*
Puts the given byte in the high order byte of the given register, and returns the error code.

parameter (the_registePtr): Pointer to the register whose high order byte is changed.
parameter (the_byte): The byte to be placed in the given register.

return value: The error code for this function as an int.
*/
int register_putHIByte(RegisterPtr the_registerPtr, uchar the_byte) {
	ushort val = 0x0000;
	if (the_registerPtr == NULL) {
		return NULL_POINTER_ERROR;
	}
	val = val | the_byte; // Low order byte of val now equals the_byte
	val = val << 8; // val now contains the_byte in high order byte, 0x00 in low order
	*the_registerPtr = *the_registerPtr & 0x00FF; // zero out high order byte of *the_registerPtr
	*the_registerPtr = *the_registerPtr | val; // puts the_byte in high order byte of *the_registerPtr
	return NO_ERROR;
}

/*
Returns the sign bit of the given register, either a 1 or 0.

parameter (the_registerPtr): Pointer to the register whose sign bit is returned.
parameter (*the_error): Pointer to int value of the error code for this function.

return value: A uchar containing the sign bit of the given register.
*/
uchar register_signOf(RegisterPtr the_registerPtr, int* the_error) {
	if (the_registerPtr == NULL) {
		*the_error = NULL_POINTER_ERROR;
		return 0;
	}
	*the_error = NO_ERROR;
	return *the_registerPtr >> 15;
}

/*
Returns the ushort value contained in the given register.

parameter (the_registerPtr): Pointer to the register whose value is returned.
parameter (*the_error): Pointer to the int value of the error code for this function.

return value: A ushort containing the value of the given register.
*/
ushort register_getRegValue(RegisterPtr the_registerPtr, int* the_error) {
	if (the_registerPtr == NULL) {
		*the_error = NULL_POINTER_ERROR;
		return 0;
	}
	*the_error = NO_ERROR;
	return *the_registerPtr;
}

/*
Puts the given ushort value in the given register, and returns the error code.

parameter (the_registerPtr): Pointer to the register where the value is put.
parameter (the_word): The value to be put into the given register.

return value: The int value of the error code for this function.
*/
int register_putRegValue(RegisterPtr the_registerPtr, ushort the_word) {
	if (the_registerPtr == NULL) {
		return NULL_POINTER_ERROR;
	}
	*the_registerPtr = the_word;
	return NO_ERROR;
}

/* End Program */
